package main

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"regexp"
	"strconv"
	"time"

	"github.com/go-xorm/xorm"
	_ "github.com/mattn/go-sqlite3"
)

var langCountryMap = map[string]string{
	"us": "English (U.S.)",
	"cn": "Chinese (Simplified)",
	"dk": "Danish",
	"nl": "Dutch",
	"au": "English (Australia)",
	"ca": "English (Cannada)",
	"gb": "English (U.K.)",
	"fi": "Finnish",
	"fr": "French",
	"de": "German",
	"id": "Indonesia",
	"it": "Italian",
	"jp": "Japanese",
	"kr": "Korean",
	"no": "Norwegian",
	"ru": "Russian",
	"es": "Spanish (Spain)",
	"se": "Swedish",
	"gr":"Greek",
	"my":"Malay",
	"tr":"Turkish",
	"pt":"Protuguese",
	"th":"Thai",
	"vn":"Vietnamese",
}

type keywords struct {
	Word string
	Time time.Time
	Hit  int
}

var engine *xorm.Engine
var maxTaskChan = make(chan int, 3)
var updateTimeMap = make(map[string]int)

func main() {
	var err error
	engine, err = xorm.NewEngine("sqlite3", "aso.db")
	checkError(err)

	for _, l := range langCountryMap {
		tableName := "keywords_" + l
		_, err = engine.Exec(fmt.Sprintf("CREATE TABLE IF NOT EXISTS `%s` (`word` TEXT, `time` INTEGER, `hit` INTEGER, PRIMARY KEY(`word`, `time`))", tableName))
		checkError(err)
	}

	for {
		for c := range langCountryMap {
			select {
			case maxTaskChan <- 1:
				fmt.Println("will fetch keywords " + langCountryMap[c])
				go fetchKeywords(c)
			}
		}
		time.Sleep(time.Hour)
		fmt.Println("===================================")
	}
}

func checkError(err error) {
	if err != nil {
		panic(err)
	}
}

func fetchCountryList() []string {
	resp, err := http.Get("http://www.asou.com/AsouHot/index")
	if err != nil {
		fmt.Println(err)
		return nil
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return nil
	}

	re := regexp.MustCompile(`<li country="(\w{2})"><span country="(\w{2})">(.+)</span></li>`)
	match := re.FindAllStringSubmatch(string(body), -1)
	list := make([]string, len(match))
	for i, m := range match {
		list[i] = m[1]
	}
	return list
}

func fetchKeywords(country string) {
	defer func() {
		<-maxTaskChan
	}()

	resp, err := http.Get(fmt.Sprintf("http://www.asou.com/AsouHot/words?country=%s&device=phone", country))
	if err != nil {
		fmt.Println(err)
		return
	}

	defer resp.Body.Close()

	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println(err)
		return
	}

	var v interface{}
	err = json.Unmarshal(body, &v)
	if err != nil {
		fmt.Println("Pase json error")
		return
	}

	m := v.(map[string]interface{})
	if int(m["errorCode"].(float64)) != 0 {
		fmt.Println(m["errorMsg"].(string))
	}

	result, ok := m["result"].(map[string]interface{})
	if !ok {
		fmt.Println("no keywords " + langCountryMap[country])
		return
	}
	updateTime, _ := strconv.Atoi(result["updateTime"].(string))
	lastUpdateTime := updateTimeMap[country]
	if updateTime == lastUpdateTime {
		fmt.Printf("%s keywords hasn't updated\n", langCountryMap[country])
		return
	}
	updateTimeMap[country] = updateTime
	// year, _ := strconv.Atoi(updateTime[0:4])
	// month, _ := strconv.Atoi(updateTime[4:6])
	// day, _ := strconv.Atoi(updateTime[6:8])
	// hour, _ := strconv.Atoi(updateTime[8:10])
	// min, _ := strconv.Atoi(updateTime[10:12])
	// second, _ := strconv.Atoi(updateTime[12:14])
	// t := time.Date(year, time.Month(month), day, hour, min, second, 0, time.Local)
	words := result["words"].([]interface{})
	tableName := "keywords_" + langCountryMap[country]
	for _, w := range words {
		ww := w.(map[string]interface{})
		word := ww["word"].(string)
		value := int(ww["value"].(float64))
		// fmt.Println(word, value)
		engine.Exec(fmt.Sprintf("INSERT INTO `%s` (`word`, `time`, `hit`) VALUES(?, ?, ?)", tableName), word, updateTime, value)
	}
	fmt.Printf("Fetch %s keywords at %d\n", langCountryMap[country], updateTime)
}
